package edu.neu.csye6200;

import java.util.*;

public class PaperList {
    private String teacher;
    private List<Paper> papers;
    private PaperSelection selections;

    public PaperList(String teacher, List<Paper> papers) {
        this.teacher = teacher;
        this.papers = papers;
        this.selections = new PaperSelection();
    }

    /**
     * For a student who has not yet selected any papers, this method randomly selects a set 
     * of papers (which has not yet been selected by any other students) from paper list, 
     * and the result should strictly satisfy preferences of the student (preferred quantity 
     * and paper type). 
     * 
     * @param student 待选择论文的学生，必须未选择过任何论文
     * 
     * @return 成功选择的论文列表，若选择成功则返回包含preferredQuantity篇论文的列表，否则抛出异常
     * 
     * @throws NoEnoughPapersException 当可选论文数量少于学生希望选择的数量时抛出
     * @throws IllegalArgumentException 当学生已选择过论文时抛出
     */
    public List<Paper> selectPaperByRandom(Student student) throws NoEnoughPapersException {
        // 检查学生是否已选择过论文
        for (Map.Entry<Paper, Student> entry : selections.getSelections().entrySet()) {
            if (entry.getValue().getName().equals(student.getName())) {
                throw new IllegalArgumentException("学生已选择过论文: " + student.getName());
            }
        }

        // 获取符合条件的未选论文
        List<Paper> availablePapers = getUnselectedPapersByType(student.getPreferredPaperType());
        int availableCount = availablePapers.size();
        
        // 检查可选论文数量是否足够
        if (availableCount < student.getPreferredQuantity()) {
            throw new NoEnoughPapersException(
                student.getName(), 
                student.getPreferredQuantity(), 
                availableCount
            );
        }

        // 随机选择论文
        List<Paper> selectedPapers = randomSelectPapers(availablePapers, student.getPreferredQuantity());
        
        // 记录选择结果
        for (Paper p : selectedPapers) {
            selections.addSelection(student, p);
        }
        
        return selectedPapers;
    }

    private List<Paper> getUnselectedPapersByType(PaperType type) {
        List<Paper> result = new ArrayList<>();
        for (Paper paper : papers) {
            if (!selections.isSelected(paper) && 
                (type == PaperType.Any || 
                 (paper instanceof Thesis && type == PaperType.Thesis) ||
                 (paper instanceof JournalPaper && type == PaperType.JournalPaper) ||
                 (paper instanceof ConferencePaper && type == PaperType.ConferencePaper))) {
                result.add(paper);
            }
        }
        return result;
    }

    private List<Paper> randomSelectPapers(List<Paper> availablePapers, int quantity) {
        List<Paper> result = new ArrayList<>();
        List<Paper> temp = new ArrayList<>(availablePapers);
        Random random = new Random();
        
        for (int i = 0; i < quantity; i++) {
            int index = random.nextInt(temp.size());
            result.add(temp.get(index));
            temp.remove(index);
        }
        
        return result;
    }

    public PaperSelection getSelectionResult() {
        return selections;
    }
}    